package cz.vse.adventura.po1715.xburj54_bursa.hra;

import cz.pecinovsky.english.pojj.adv_framework.game_gui.IBagG;
//import cz.pecinovsky.english.pojj.adv_framework.game_txt.IBag;
import cz.pecinovsky.english.pojj.adv_framework.game_gui.IListener;
import cz.pecinovsky.english.pojj.adv_framework.game_txt.INamed;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;


/*******************************************************************************
 * Instance třídy {@code Kapsa} představují úložiště, do nichž si hráči
 * odkládají sebrané předměty.
 *
 * @author Jan Bursa
 * @version 1.02,  16.12.2010
 */
public class Kapsa implements IBagG
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Maximální kapacita batohu*/
    private static final int KAPACITA = 3;

    /** Schránka na přenášené předměty.*/
    private static final Kapsa kapsa = new Kapsa();

//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================
    
    /** Kolekce předmětů v batohu. */
    private final Collection<Předmět> obsah = new ArrayList<Předmět>();

    /** Posluchači očekávající oznámení o změně předmětů v batohu. */
    private Collection<IListener<IBagG>> posluchači =
                                       new ArrayList<IListener<IBagG>>();

//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================

    /***************************************************************************
     * Vrátí kapacitu kapes, tj. kolik předmětů se do něj vejde.
     *
     * @return Kapacita kapes
     */
    @Override
    public int getCapacity()
    {
        return KAPACITA;
    }

    /***************************************************************************
     * Vrátí kolekci předmětů uložených v kapsách.
     *
     * @return Kolekce predmetu v kapsách
     */
    @Override
    public Collection<Předmět> getObjects()
    {
         return Collections.unmodifiableCollection(obsah);
    }



//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

     static Kapsa getKapsa()
    {
        return kapsa;
    }

/***************************************************************************
     * Vytvoří prázdnou Kapsu.
     */
    public Kapsa()
    {
    }

//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== OSTATNÍ NESOUKROMÉ  METODY INSTANCÍ =======================================


    /***************************************************************************
     * Zjistí, zda je v zadané kolekci pojmenovaný objekt se zadanym nazvem
     * a vrátí jej.
     *
     * @param  nazev Nazev hledaného pojemnovaného objektu
     * @param  kolekce Kolekce, ve které pojmenovaný objekt hledám
     * @return Byl-li v kolekci objekt se zadanýžm názvem, vrati jej,
     *         jinak vrati prazdny odkaz {@code null}
     */
    public static INamed najdi(String nazev,
                               Collection<? extends INamed> kolekce)
    {
        nazev = nazev.toLowerCase();
        for (INamed ip : kolekce) {
            if (ip.getName().toLowerCase().equals(nazev)) {
                return ip;
            }
        }
        return null;
    }

    /***************************************************************************
     * Inicializuje jedináčka a připraví jej pro novou hru.
     */
    static void inicializuj()
    {
        kapsa.obsah.clear();
    }


    /***************************************************************************
     * Zjistí, zda batoh obsahuje předmět zadaný svým názvem.
     *
     * @param  název Název předmětu v batohu
     * @return {@code true} pokud je předmět v kapse, jinak {@code false}
     */
    boolean obsahuje( String název ) {
        Předmět nasel = (Předmět)najdi(název, obsah);
        return (nasel != null);
    }


    /***************************************************************************
     * Přidá zadaný předmět do kapes.
     *
     * @param  předmět Předmět přidávaný do kapes
     * @return {@code true} pokud byl předmět do kapes vložen
     */

    boolean pridej( Předmět predmet ) {
        boolean pridavam = (obsah.size() < KAPACITA)  &&  obsah.add( predmet );
        noticeListeners();
        return pridavam;
    }


    /***************************************************************************
     * Vyjme z kapes předmět zadaný svým názvem.
     *
     * @param  název Název předmětu vybíraného z kapes
     * @return Byl-li předmět v kapsách, vrátí odkaz na předmět,
     *         jinak vrátí prázdný odkaz {@code null}
     */
    Předmět vyjmi( String nazev ) {
        Předmět nasel = (Předmět)najdi(nazev, obsah);
        if (nasel != null) {
            obsah.remove(nasel);
            noticeListeners();
        }
        return nasel;
    }


    /** {@inheritDoc} */
    @Override
    public String toString()  {
        return "V kapsách se nachází:" + obsah;
    }

    /***************************************************************************
     * Přidá zadaného posluchače do seznamu posluchačů,
     * které zpravuje o výskytu očekávané události.
     *
     * @param listener Přihlašovaný posluchač
     */
    //@Override
    public void addListener(IListener<IBagG> listener) {
        posluchači.add(listener);
    }

    /***************************************************************************
     * Odebere zadaného posluchače do seznamu posluchačů,
     * které zpravuje o výskytu očekávané události.
     *
     * @param listener Odhlašovaný posluchač
     */
    //@Override
    public void removeListener(IListener<IBagG> listener) {
        posluchači.remove(listener);
    }

//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================

    /***************************************************************************
     * Upozorní přihlášené posluchače, že se obsah batohu změnil
     */
    private void noticeListeners() {
        for (IListener<IBagG> listener : posluchači) {
            listener.notice(this);
        }
    }
    //== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTOVACÍ METODY A TŘÍDY ==================================================
//
//     /***************************************************************************
//      * Testovací metoda.
//      */
//     public static void test()
//     {
//         Kapsa x = new Kapsa();
//     }
//     /** @param args Parametry příkazového řádku - nepoužívané. */
//     public static void main(String[] args)  {  test();  }
}